#ifndef PTHREAD_POOL_H_ 
#define PTHREAD_POOL_H_

#include <iostream>
#include <queue>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>

#define PTHREAD_POOL_MAX 1024
#define TASK_QUEUE_MAX 1024


using namespace std;

//定义任务结构体
typedef void (*task)(void*);

typedef struct taskitem
{
    task func;      //函数指针
    void* arg;      //函数参数
}Taskitem;




//定义线程池
class pthread_pool
{
private:
    Taskitem* m_taskqueue;      //任务队列
    pthread_t* m_pthreads;      //线程池

    pthread_mutex_t m_Mutex;    //互斥锁
    pthread_cond_t m_not_full;  //未满信号
    pthread_cond_t m_not_empty; //未空信号
    bool stop;                  //结束指令
    int presently_task;         //目前任务数
    int pthread_num;            //目前进程数

    int queue_front;    /* task_queue队头下标 */
    int queue_rear;     /* task_queue队尾下标 */

//函数内容

    //创建线程函数
    void cread_pool()
    {
        for (int i = 0; i < PTHREAD_POOL_MAX; ++i)
        {
            if (pthread_create(&(m_pthreads[i]),NULL,&work,(void*)this) != 0)
            {
                printf("第%d个线程创建失败\n",i+1);
                stop = true;
                break;
            }
            pthread_detach(m_pthreads[i]);
            pthread_num++;
            printf("创建第%d个线程创建完成\n",i+1);
        }
        
    }
    
public:
    pthread_pool()
     : stop(false)
     , presently_task(0)
     , pthread_num(0)
     , queue_front(0)
     , queue_rear(0)
    {
        m_taskqueue = new Taskitem[TASK_QUEUE_MAX];
        if (m_taskqueue == nullptr)
        {
            perror("队列分配出错\n");
            return ;
        }
        
        m_pthreads = new pthread_t[PTHREAD_POOL_MAX];
        if (m_pthreads == nullptr)
        {
            perror("线程池分配出错\n");
            return ;
        }

        //初始化条件变量与互斥锁
        pthread_mutex_init(&m_Mutex,NULL);
        pthread_cond_init(&m_not_empty,NULL);
        pthread_cond_init(&m_not_full,NULL);

        //创建线程
        cread_pool();
    }
   
   
    ~pthread_pool()
    {
        //停止所有线程
        pthread_mutex_lock(&m_Mutex);
        stop = true;
        pthread_cond_broadcast(&m_not_empty);//唤醒所有进程让其执行停止命令
        pthread_mutex_unlock(&m_Mutex);//解锁

        //销毁资源
        delete []m_taskqueue;
        delete []m_pthreads;
        pthread_mutex_destroy(&m_Mutex);
        pthread_cond_destroy(&m_not_empty);
        pthread_cond_destroy(&m_not_full);
        m_taskqueue = nullptr;
        m_pthreads = nullptr;

        cout <<"线程池正常结束"<<endl;
    }

    
    //线程工作函数
    void behavior()
    {
        Taskitem task;      //注意这里需要对象，非指针
        while (1)
        {
            //获取锁
            pthread_mutex_lock(&m_Mutex);

            //查看任务数量
            while ( (presently_task == 0 && !stop) )
            {
                pthread_cond_wait(&m_not_empty,&m_Mutex);//挂起等待，并释放锁
            } 

            //停止指令
            if(stop == true)
            {
                pthread_mutex_unlock(&m_Mutex);
                --pthread_num;
                pthread_exit(NULL);
            }  

            //获得了锁，且有任务
            task.func = m_taskqueue[queue_front].func;
            task.arg = m_taskqueue[queue_front].arg;
            presently_task--;
            queue_front = (queue_front+1)%TASK_QUEUE_MAX;//设置为循环队列

            pthread_mutex_unlock(&m_Mutex);//获取任务后释放锁
            pthread_cond_signal(&m_not_full);
            (*(task.func))(task.arg);
        }      
    }

    //线程任务过度函数
    static void* work(void *arg)
    {
        pthread_pool *pool = (pthread_pool*)arg;
        pool->behavior(); 
    }

    //任务队列添加函数
    void addtask(task func ,void* arg)
    {
        pthread_mutex_lock(&m_Mutex);
        //判断任务对列是否已满
        if (presently_task == TASK_QUEUE_MAX)
        {
            pthread_cond_wait(&m_not_full,&m_Mutex);//释放锁，并等待未满信号
        }
        
        //队列未满，添加任务唤醒线程
        m_taskqueue[queue_rear].func = func;
        m_taskqueue[queue_rear].arg = arg;
        ++presently_task;
        queue_rear = (queue_rear +1)%TASK_QUEUE_MAX;

        //完成添加释放锁并发出未空信号
        pthread_mutex_unlock(&m_Mutex);
        pthread_cond_signal(&m_not_empty);        
    }

    void end_pool()
    {
        stop = true;
    }

};





#endif